在ReactNative开发中,目前为止,活动页面之间的跳转使用Navigator来实现。但是在实际使用中却有着不为人知的秘密……
Navigator allow you to manage the navigation in your app between various “scenes” (another word for screens). They manage a route stack and allow you to pop, push, and replace states. In this way, they are similar to the html5 history API. Navigator re-implements that functionality entirely in JavaScript as a React component. A corollary of this is that Navigator will be compatible with Android and iOS
——Facebook ReactNative Official Introduction
##基本概念
navigator
: 一个用来管理所有界面对象的栈,人称之 “路由栈”, 学名 “导航”。route
: 路由栈里的每一个对象,称之为 “路由”,用来存储每一个页面组件以及一些需要传递给对应界面的props参数。
使用Navigator来导航整个App页面
在Android中,我们都知道管理Activity的Task栈。由此可知,我们需要把Navigator放在一个常驻的界面中。因此我们在这里放在整个ReactNative工程的入口——index.ios.js/index.android.js 中。
为项目添加Navigator控制
- 第一步需要做的依旧是引入Navigator组件 (以下React已import导入)
- 加入全局的名字空间以方便使用
let { Navigator } = React
- 或者以
React.Navigator
的方式直接使用
- 加入全局的名字空间以方便使用
使用Navigator组件
return (
<Navigator style = {styles.container}
initialRoute={{
name: 'HomePage'// 可选
component: HomePage
}}
configureScene={(route) => {
return Navigator.SceneConfigs.VerticalDownSwipeJump
}}
renderScene={(route, navigator) => {
return <route.component navigator={navigator} {...route} {...route.passProps}/>
}}/>
)initialRoute
: 初始路由,也就是我们需要在navigator栈底放置的路由,因为此时也是栈顶,因此也就是初始化整个App的首页。configureScene
: 设置页面切换动画,具体的值大家可以在node_modules/react-native/Libraries/CustomComponents/Navigator/NavigatorSceneConfigs.js
源库中找到。或者直接在sublime Text 3 中使用命令command+p
命令,然后输入NavigatorSceneConfigs
进行文件搜索。笔者看了一下,大概有不到十种动画,这里就不做具体介绍了。renderScene
: 渲染当前路由场景,也就是渲染栈顶路由。回调方法里一个参数是当前路由route,另一个是navigator 路由栈。这里需要细讲一下:route
: 路由里包含一个必要的component变量和一些可选的参数,而component则就是当前需要渲染的组件。其他的一些可选的参数也是以键值对的方式保存在route对象中,并在这里以属性的方式传递给对应的component组件中。navigator
: 这是Navigator组件在本回调方法中的参数,也就是我们在前边提到的路由栈。会在每次渲染新route的时候以属性的形式传递给route中component的对象。它可以在对应的场景中做一些操作,这里我们给出官方的部分文档:- getCurrentRoutes() - 获取当前栈里的路由,也就是push进来,没有pop掉的那些。
- jumpBack() - 跳回之前的路由,当然前提是保留现在的,还可以再跳回来,会给你保留原样。
- jumpForward() - 上一个方法不是调到之前的路由了么,用这个跳回来就好了。
- jumpTo(route) - 跳转到已有的场景并且不卸载。
- push(route) - 跳转到新的场景,并且将场景入栈,你可以稍后跳转过去
- pop() - 跳转回去并且卸载掉当前场景
- replace(route) - 用一个新的路由替换掉当前场景
- replaceAtIndex(route, index) - 替换掉指定序列的路由场景
- replacePrevious(route) - 替换掉之前的场景
- immediatelyResetRouteStack(routeStack) - 用新的路由数组来重置路由栈
- popToRoute(route) - pop到路由指定的场景,其他的场景将会卸载。
- popToTop() - pop到栈中的第一个场景,卸载掉所有的其他场景。
{...route}
这是一句 es6 语法,表示将route中所有的键值对以属性赋值的方式展开,也就是{name: 'pober', gender: 'man'}
到name = 'pober' gender = 'man'
之间的转换。这样就把route对象中所有的键值对就很容易地放到route.component组件的props属性中去啦~因此,这个语法在自定义控件的时候也经常用到,主要用来兼容组件中其他所有的属性,如自定义ListView兼容官方ListView的所有属性。passProps
这是一个我们自己定义的key,后边会提到。同样是可选的
在对应页面中使用navigator路由栈进行基本的操作
在上边也提到了navigator的一些列方法。这里我们核心介绍一下push和pop的操作。push(route)
: 跳转到下一个场景同时将它入栈。我们看一下以下代码this.props.navigator.push({
component: NextPage,
passProps: {name: 'pober'} // 传递的参数(可选),{}里都是键值对 ps: test是关键字
})
以上这段代码可以放在任何你需要监听跳转的地方,同样也可以传递任何你想要的参数。
* 这里括号里的部分就是一个对象。我们也可以把它单独拿出来赋给route变量 (如果不能理解的话)
* `component`:即就是我们需要呈现的组件
* `passProps` 这是[NavigatorIOS](http://facebook.github.io/react-native/docs/navigatorios.html#content) 中常用的一个属性,这里我们加上是为了让它们看起来更加统一一些。当然啦,既然是手动加的,那命名当然是随意的了,只要和Navigator组件里声明的一样即可。
注意,test应该是React中的某个关键字,如果在passProps里声明的话,在下一个界面里是拿不到的。 当然,有了前边{...route}
我们显然是没必要再去包裹一层参数,当然如果不是为了语义上的准确
pop()
顾名思义就是一个对navigator栈弹栈的过程,这经常发生在NavigationBar中的Back事件中。
项目实战
这里我们只进行几个必要的操作
将上次的History页面抽取出一个单独的js文件,我们在这里叫做
History.js
,放在了js.core
文件夹下,并在index.ios.js中引入之。然后在index.ios.js中按照以上步骤加入Navigator组建的使用,设置初始路由为History页面,如果此时运行的效果和之前一样的话,就算是OK啦…
接着我们开始利用Navigator进行页面跳转的实践吧~
创建一个新的页面,我们叫HelloWorld.js吧,然后在History页面导入之,然后进行路由跳转即可。
History 更改如下代码:_renderItem (contentData, sectionID, highlightRow) {
return (
<TouchableHighlight
onPress = {() => this.props.navigator.push({
component: HelloWorld,
passProps: {geeker: 'pober'}
})}>
<View style={styles.itemContainer}>
<Text style={[styles.title]}>{contentData.title}</Text>
<Image source={{uri: contentData.uri}}
style={styles.thumbnail}/>
</View>
</TouchableHighlight>
)
}
```
其实也就是给外层的`TouchableHighlight`添加一个点击事件,然后添加的代码和上个模块的`push`操作一样。我们还加入了一个key为geeker的键值对,值是我的名字`pober`。
4. 此时,做完以上三点,已经能够从History页面跳转到HelloWorld页面了。接下来我们再做一个navigator栈的操作——`pop`
很简单,这里我们直接在HelloWorld页面手动执行这个操作就可以了。其实,自带的右滑返回也是这个操作...render () {
return (
<TouchableOpacity onPress = {() => this.props.navigator.pop()}> <Text>{this.props.geeker}</Text> </TouchableOpacity>
)
}`
这里是HelloWorld的核心代码,我们使用了一个按钮,然后上边显示了我们在上一个界面中传入的geeker
变量,值当然就是伦家的名字pober
啦…点击之后,我们很简单地调用了navigator的pop()
方法。
HelloWorld
页面截图:
结语
路漫漫其修远兮,吾将上下而求索
未来的路还很长,每个人都在努力的追逐时代的步伐,科技的脚步。现在ReactNative已经更新到 0.20.0了,相信在未来的不久,这位酷似大卫的神级偶像 扎克伯格 将会带领我们走向全新的潮流。
项目源码
以上部分代码已经放在 我的Github上,欢迎来访查看。
作者:poberWong
发布时间:2016-02-21 19:30
更新时间:2016-02-28 16:07
版权声明:自由转载 - 不可商用 - 不可衍生 - 保持署名 (请遵守:CreativeCommons 3.0协议)